﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Interop;
namespace JBrute
{

      
   /// <summary>
   /// Interaction logic for Window1.xaml
   /// </summary>
   public partial class MainWindow : Window
   {

      [DllImport("User32.dll")]
      protected static extern int
                SetClipboardViewer(int hWndNewViewer);

      [DllImport("User32.dll", CharSet = CharSet.Auto)]
      public static extern bool
             ChangeClipboardChain(IntPtr hWndRemove,
                                  IntPtr hWndNewNext);
      [DllImport("user32.dll", CharSet = CharSet.Auto)]
      private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);


      bool m_bSortAscending; // delete, replace with state of column header
      GridViewColumn _lastHeaderClicked = null;
      ListSortDirection _lastDirection = ListSortDirection.Ascending;
      IntPtr viewerHandle = IntPtr.Zero;
      IntPtr installedHandle = IntPtr.Zero;
      private bool IsFirstTime_Clipboard = true;
      public String lastClipboardCopy = String.Empty;
      public MainWindow()
      {
         InitializeComponent();
         m_bSortAscending = true;
         // Setup Commands
         CommandBinding ChangeIMEModeBinding = new CommandBinding(Commands.ChangeIMEModeCommand, Commands.ExecutedChangeIMEModeCommand, Commands.CanExecuteCommand);
         CommandBindings.Add(ChangeIMEModeBinding);
         KeyGesture ChangeIMEModeGesture = new KeyGesture(Key.I, ModifierKeys.Alt);
         KeyBinding ChangeIMEModeKeyBinding = new KeyBinding(Commands.ChangeIMEModeCommand, ChangeIMEModeGesture);
         this.InputBindings.Add(ChangeIMEModeKeyBinding);

         CommandBinding SetFocusTextBinding = new CommandBinding(Commands.SetFocusTextCommand, Commands.ExecutedSetFocusTextCommand, Commands.CanExecuteCommand);
         CommandBindings.Add(SetFocusTextBinding);
         KeyGesture SetFocusTextGesture = new KeyGesture(Key.D, ModifierKeys.Alt);
         KeyBinding SetFocusTextKeyBinding = new KeyBinding(Commands.SetFocusTextCommand, SetFocusTextGesture);
         this.InputBindings.Add(SetFocusTextKeyBinding);

         CommandBinding CopyLVBinding = new CommandBinding(ApplicationCommands.Copy, Commands.CopyLVExecuted, Commands.CanExecuteCommand);
         lvResults.CommandBindings.Add(CopyLVBinding);

      }
      void GridViewColumnHeaderClickedHandler(object sender,
                                            RoutedEventArgs e)
      {
         GridViewColumnHeader headerClicked =
               e.OriginalSource as GridViewColumnHeader;
         ListSortDirection direction;

         if (headerClicked != null)
            direction = UpdateSortUI(headerClicked.Column, true);
      }

      private ListSortDirection UpdateSortUI(GridViewColumn headerClicked, bool bToggle)
      {
         ListSortDirection direction = _lastDirection;
         //if (headerClicked != null && headerClicked.Role != GridViewColumnHeaderRole.Padding)
         if (headerClicked != null )
            {
               if (headerClicked != _lastHeaderClicked)
               {
                  direction = ListSortDirection.Ascending;
               }
               else if (bToggle)
            {
               if (_lastDirection == ListSortDirection.Ascending)
               {
                  direction = ListSortDirection.Descending;
               }
               else
               {
                  direction = ListSortDirection.Ascending;
               }
            }

            if (direction == ListSortDirection.Ascending)
            {
               headerClicked.HeaderTemplate =
                 Resources["HeaderTemplateArrowUp"] as DataTemplate;
            }
            else
            {
               headerClicked.HeaderTemplate =
                 Resources["HeaderTemplateArrowDown"] as DataTemplate;
            }

            // Remove arrow from previously sorted header
            if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked)
               {
                  _lastHeaderClicked.HeaderTemplate = null;
               }
            _lastHeaderClicked = headerClicked;
            _lastDirection = direction;
            m_bSortAscending = (_lastDirection == ListSortDirection.Ascending); // to do dump the boolean and replace with state of HEader
            ViewModel.Instance.SearchUtil(FindMeText.Text, ViewModel.SearchType.Lookup);
         }
         return direction;
      }
      // Returns the SQLite ORDER BY clause for queries other than VOCABLIST
      public String getSort(ref String FromTable)
      {
         String sort = String.Empty;
         String header = "Kanji";
         if (_lastHeaderClicked != null)
            header = _lastHeaderClicked.Header as String ;
         if ("Kanji" == header)
            FromTable = "k_ele";
         else if ("Kana" == header)
            FromTable = "r_ele";
         else if ("English" == header)
            FromTable = "gloss";
         sort = "ORDER BY "+FromTable+".value " + (m_bSortAscending ? "ASC" : "DESC");
         return (sort);
      }

      private void FindMeText_Changed(object sender, TextChangedEventArgs e)
      {
         StackTrace stackTrace = new StackTrace();           // get call stack
         StackFrame[] stackFrames = stackTrace.GetFrames();  // get method calls (frames)
         foreach (StackFrame s in stackFrames)
            if (s.GetMethod().Name == "SearchClipboardData")
               return; // instead, this is handled by the SearchClipboardData method itself.

         System.Windows.Controls.GridView grdView = lvResults.View as System.Windows.Controls.GridView;         
         GridViewColumn theColumn = null;
         Char c = String.IsNullOrEmpty(FindMeText.Text) ? 'A' : FindMeText.Text[0] ; 
         if (ViewModel.isKanji(c))
            theColumn = grdView.Columns[0];
         else if (ViewModel.isKana(c))
            theColumn = grdView.Columns[1];
         else
            theColumn = grdView.Columns[2];
         ///  Make this take a Column and then use the HeaderTemplate of the column.
         ///  The ColumnHeader object is TOO elusive
         UpdateSortUI(theColumn, false);
      }

      private void ChangeIMEMode(object sender, MouseButtonEventArgs e)
      {
         Commands.ExecutedChangeIMEModeCommand(sender, null);
      }

      private void HistoryNavigate(object sender, RoutedEventArgs e)
      {
         Button b = sender as Button;
         if (b.Name.Equals("btnFwd"))
            ViewModel.Instance.CurrentHistoryIndex++;
         else if (b.Name.Equals("btnBack"))
            ViewModel.Instance.CurrentHistoryIndex--;
         ResultsItem ri = ViewModel.Instance.HistoryList[ViewModel.Instance.CurrentHistoryIndex];
         ViewModel.Instance.htmlhelper.Display(ri, false);
      }

      private void Window_ContentRendered(object sender, EventArgs e)
      {
         toolBar.DataContext = ViewModel.Instance;
         statusBar.DataContext = ViewModel.Instance;
         foreach (CultureInfo ci in InputLanguageManager.Current.AvailableInputLanguages)
         {
            if (ci.TwoLetterISOLanguageName == "ja")
            {
               ViewModel.Instance.IMEMode = ViewModel.IMEModeType.Off; // Disabled --> Off.
               break;
            }
         }
         if (ViewModel.Instance.IMEMode == ViewModel.IMEModeType.Disabled)
         {
            String msg = "Windows does not have Japanese language support installed.";
            msg += "\n\nJBrute requires 'Asian Language Support' be installed on the Operating System";
            msg += "\n and will not work properly until it is (Japanese characters won't show).";
            msg += "\n\nYou should 'Close' this dialog, exit JBrute and";
            msg += "\n install the Asian Language Support for the OS.";
            msg += "\n There's nothing else to buy; it shipped with the OS; it's just not installed.";
            msg += "\n\nFor detailed instructions on installing Japanese language support,";
            msg += "\n try Start/Control Panel/Regional and Language Options or";
            msg += "\n check the JBrute Help file";
            msg += "\n (Appendices / Reading and Writing Japanese Letters in Windows)";
            MessageDialog.Show(msg, "Japanese Language Support NOT Installed");
         }
      }

      protected override void OnSourceInitialized(EventArgs e)
      {
         base.OnSourceInitialized(e);
         HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
         if (hwndSource != null)
         {
            installedHandle = hwndSource.Handle;
            hwndSource.AddHook(new HwndSourceHook(this.hwndSourceHook));
         }
      }
      private void ToggleClipBoard(object sender, RoutedEventArgs e)
      {
         if (ViewModel.Instance.ClipBoardMonitor)
         {
            IsFirstTime_Clipboard = true;
            viewerHandle = (IntPtr)SetClipboardViewer((int)installedHandle);
         }
         else
         {
            ChangeClipboardChain(installedHandle, viewerHandle);
         }
      }
      private void TogglePinToTop(object sender, RoutedEventArgs e)
      {
         this.Topmost = ViewModel.Instance.PinToTop;
      }
      private void SearchClipboardData()
      {
         if (!ViewModel.Instance.ClipBoardMonitor)
            return;
         IDataObject iData = null;
         for (int i = 0; i < 10; i++)
         {
            try
            {
               iData = Clipboard.GetDataObject();
               break;
            }
            catch (System.Runtime.InteropServices.COMException)
            {
               System.Threading.Thread.Sleep(10);
            }
         }
         String[] aString = iData.GetFormats();
         if (iData.GetDataPresent("UnicodeText", true))
         {
            String LookMeUp = (String)iData.GetData("UnicodeText", true);
            if (lastClipboardCopy.Equals(LookMeUp))
               return; // Sometime we get called multiple times with the same data.
            lastClipboardCopy = LookMeUp;
            TextBlock tb = Mouse.DirectlyOver as TextBlock;
            if (tb != null)
               return; // over results pane of this app
            //FindMeText.Text = LookMeUp;
            ViewModel.Instance.SearchUtil(LookMeUp, ViewModel.SearchType.VocabList);
         }
      }

      IntPtr hwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
      {
         // defined in winuser.h
         const int WM_DRAWCLIPBOARD = 0x308;
         const int WM_CHANGECBCHAIN = 0x030D;
         if (IsFirstTime_Clipboard)
         {
            IsFirstTime_Clipboard = false;
            return IntPtr.Zero;
         }
         switch (msg)
         {
            case WM_CHANGECBCHAIN:
               this.viewerHandle = lParam;
               if (this.viewerHandle != IntPtr.Zero)
               {
                  SendMessage(this.viewerHandle, msg, wParam, lParam);
               }

               break;

            case WM_DRAWCLIPBOARD:
               SearchClipboardData();
               if (this.viewerHandle != IntPtr.Zero)
               {
                  SendMessage(this.viewerHandle, msg, wParam, lParam);
               }

               break;

         }
         return IntPtr.Zero;
      }
      protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
      {
         ChangeClipboardChain(this.installedHandle, this.viewerHandle);
         int error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
         e.Cancel = error != 0;

         base.OnClosing(e);
      }
      protected override void OnClosed(EventArgs e)
      {
         this.viewerHandle = IntPtr.Zero;
         this.installedHandle = IntPtr.Zero;
         base.OnClosed(e);
      }

      private void details_LoadCompleted(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e)
      {
         details.Document.AttachEventHandler("onselectionchange", new EventHandler(OnSelectionChange));
      }
      private void OnSelectionChange(object sender, EventArgs e)
      {
         FindMeText.Text = GetSelection(details);
      }
      // When the user selects text, they mean "what does this mean."  Enter this as the next search term.
      private String GetSelection(System.Windows.Forms.WebBrowser webBrowser)
      {
         mshtml.IHTMLDocument2 doc = (mshtml.IHTMLDocument2)details.Document.DomDocument;
         mshtml.IHTMLSelectionObject sel = doc.selection;
         mshtml.IHTMLTxtRange range = (mshtml.IHTMLTxtRange)sel.createRange();
         return range.text;
      }

      private void HelpClick(object sender, RoutedEventArgs e)
      {
         String AppPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
         String path = AppPath + "\\..\\doc\\jbrute.chm";
         ProcessStartInfo info = new ProcessStartInfo(path);
         info.UseShellExecute = true;
         info.Verb = "open";
         Process.Start(info);
      }

      private void LVGotFocus(object sender, RoutedEventArgs e)
      {
         ListViewItem lvi = e.OriginalSource as ListViewItem;
         if (lvi != null)
            lvi.IsSelected = true;
      }

      private void TXTGotFocus(object sender, RoutedEventArgs e)
      {
         TextBox txt = sender as TextBox;
         if (txt != null)
            txt.SelectAll();
      }

      private void AboutClick(object sender, RoutedEventArgs e)
      {
         About about = new About();
         about.ShowDialog();
      }

   }
}
